Repository navigation
chore: sync fork with upstream (v2.5.6, #338–#456) - #83
Merged
Merged
Conversation
chattymin#375) Normalize candy window epoch timestamps and require window-scale advancement (>= 30m for session, >= 24h for weekly) before rearming candy grants. This prevents Anthropic API microsecond fluctuations, Codex ±1s timestamp jitter, and rolling window drift from repeatedly rearming at 100% utilization.
…after Back (chattymin#435) * test(collection): add a pure page lookup for the Pokédex grid DexScrollPager.page(containing:in:pageSize:) returns the page that shows a species, or 0 when it is nil or filtered out. Not wired up yet; the next commit uses it to return to the viewed page after Back. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(collection): return to the viewed Pokédex page after Back The detail page replaces the grid, so Back rebuilt DexGridView and its page state started over at page 1. CollectionView now remembers the species whose detail page was closed and the rebuilt grid starts with it selected, deriving the page from that selection. Opening a species from a Home sprite now also lands on its page on Back. The anchor is used once, so a later rebuild (segment switch) still starts on page 1. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(collection): keep the catch log row in view after Back The catch log sits in the same branch the detail page replaces, so Back scrolled it to the top. The row that opened the detail page is now scrolled back to the center. The scroll waits one turn after the log appears: before the first layout the lazy rows above it are estimated and the scroll stopped short of the row. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: log the detail-page remount that reset the Pokédex page Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: show Pokédex and catch log Back comparison Sample-data renders of the real CollectionView for the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(collection): correct the catch log scroll after rows are measured CI showed the restored log stopping a row short of the row that opened the detail page. The first scrollTo places the target with estimated heights for the lazy rows; once the rows it reveals are measured they push the target off its spot. Scroll again after that layout pass. A single scroll fails the test locally too. The tests also retry a press until the screen changes: right after a transition the view tree can still hit-test the previous screen, which made a Back press miss on CI. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: record the catch log scroll CI finding Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(collection): set the grid return anchor only when Back lands on the grid Back always stored the closed species as the grid's return anchor, but only the grid's onAppear clears it. When Back returned to the catch log (the detail page was opened from a log row, or from a Home sprite while the log segment was selected), the anchor stayed, and the next switch to the Pokédex segment opened on that species' page with it selected instead of page 1. testBackToTheLogLeavesTheGridOnItsFirstPage covers that path and fails when the anchor is stored unconditionally again. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(collection): reopen the Pokédex page after Back without selecting the species The grid found its return page by starting with the closed species as its selection. That brought back the selection border and the footer line, which nothing had shown since the detail page started replacing the grid (chattymin#264), and made the grid behave unlike the catch log, which only scrolls back to the row. DexGridView now keeps the anchor in its own state and uses it only to pick the page. testBackFromDetailReturnsToThePageOfThatSpecies asserts that the footer does not name the species and fails when the anchor selects it again. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: re-render the Pokédex Back comparison without the selection Sample-data render of the real CollectionView after Back: page 2 with no species selected. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Generalize the Unown letter forms (chattymin#288) to every generation 1-5 species whose forms all have an animated Black/White sprite: Castform, Deoxys, Burmy/Wormadam, Cherrim, Shellos/Gastrodon, Rotom, Giratina, Shaymin, Arceus, Basculin, Darmanitan, Deerling/Sawsbuck, the forces of nature, Kyurem, Keldeo, Meloetta and Genesect. The form belongs to the individual, is drawn once for the whole line and is resolved per species. Saves use form/pendingForm/representativeForm and still read the former Unown keys.
…n#446) * fix(settings): collapse automatic backup history by default * test(settings): reveal snapshot disclosure before locating it * test(settings): stabilize native snapshot capture and disclosure clicks * fix(settings): use a native button for backup history * test(settings): capture snapshot history across native viewports * test(settings): recognize native snapshot renders in viewport strips
Correct Sonnet 5.5 cache-read estimates across persisted usage caches. Carry the current form into backup summaries and thumbnails. Preserve Antigravity refresh credentials after transient grant failures. Explain default-form metadata beside alternate appearances, with native rendering and focused regression guards.
…min#448) Retain SwiftUI App startup and replace the unused Settings { EmptyView() } scene with _EmptyScene(). Settings remain in the existing popover; startup, menus, activation policy, and popover placement otherwise match main. Stabilize the Korean chart OCR fixture using exact captions among equally highest-confidence candidates. Preserve diagnostic candidates and CI fixture images. Validation: final PR build passed; 1,520 local tests excluding window-presenting suites passed with 16 skipped and zero failures. The empty-scene entry point compiles against SDK14.5 and26.5 targeting macOS14. Full CI passed: 1,560 tests, 16 skipped, zero failures, 93.80% logic-core line coverage; secret scan passed. Local app replacement is deferred to avoid desktop interruption.
…ole files (chattymin#338) On an account with a large Claude Code history (~2GB of session logs in the current month, single files up to 274MB) the cold scan pegged a core for over a minute without finishing, and because the blob cache is keyed on whole-file mtime+size, the active session file was re-parsed from byte zero on every refresh. Three changes: - ISO8601Parser reuses one lock-guarded formatter pair instead of allocating an ISO8601DateFormatter per line (the dominant sampled cost). - parseClaudeFile scans lines at the byte level via Data/FileHandle rather than materializing the file as a String and splitting into Substrings. - Blob records a per-file byte offset; when a file has only grown, only the appended tail is parsed and merged. Same-size or shrunk files are re-read from the start. Older cache files without the key still load. Measured on the history above: cold start ~15s then idle (was 60s+ and never completed), steady-state refresh stays at 0% CPU. Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Patrick.Park <pdm001125@naver.com>
* fix: parse Claude session logs incrementally instead of re-reading whole files On an account with a large Claude Code history (~2GB of session logs in the current month, single files up to 274MB) the cold scan pegged a core for over a minute without finishing, and because the blob cache is keyed on whole-file mtime+size, the active session file was re-parsed from byte zero on every refresh. Three changes: - ISO8601Parser reuses one lock-guarded formatter pair instead of allocating an ISO8601DateFormatter per line (the dominant sampled cost). - parseClaudeFile scans lines at the byte level via Data/FileHandle rather than materializing the file as a String and splitting into Substrings. - Blob records a per-file byte offset; when a file has only grown, only the appended tail is parsed and merged. Same-size or shrunk files are re-read from the start. Older cache files without the key still load. Measured on the history above: cold start ~15s then idle (was 60s+ and never completed), steady-state refresh stays at 0% CPU. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(home): label the usage recap control The chart icon was the only way into week, month, and year recaps, and it did not look like a button. Show a short localized label inside a light capsule. * fix(home): preserve period values beside the recap label * test(home): match OCR languages to period fixtures --------- Co-authored-by: notcadenwhitt-stack <notcadenwhitt@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Patrick.Park <pdm001125@naver.com>
Use an unambiguous word for the oldest catch while retaining exact OCR, click, Back navigation and scroll reset assertions. Adapt the fixture repair from c7c2d7a and record the CI failure in the defect log. Co-authored-by: 서민수 <sms@bbros.kr> Co-authored-by: Codex <noreply@openai.com>
Merge chattymin/PokeTokenBar main (17 commits) into the fork. Conflict resolutions that adapt upstream changes to fork-only code: - Sonnet 5.5 cache-read price and the locked ISO8601 parser ported into PokeTokenBarShared, where the fork keeps ModelPricing and ISO8601Parser; the Mac keeps its typealiases. - Empty Settings windows (chattymin#448): adopted _EmptyScene(). Without a Settings scene there is no system ⌘, item, so SettingsMenuItem.install adds the fork's own app-menu item (retargets an existing one if present). The unreachable SettingsSceneBridge fallback is removed. - Antigravity transient refresh failure: ported upstream's fix onto the fork's AntigravityRefreshOutcome model. An expired Keychain credential whose grant fails temporarily now throws AntigravityTokenRefreshError.transient instead of returning the dead token (which 401'd and invalidated the only refresh token). Upstream's tests rewritten onto tokenRefresher. - Generic Pokémon forms (chattymin#376): the iPhone payload stays Unown-only; the export maps the new PokemonForm API onto it and no longer risks sending other species' forms as Unown letters. - README, SettingsView state and defect-log: kept both sides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 of 10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings the fork up to
chattymin/PokeTokenBarmain (v2.5.6 plus everything merged since, chattymin#338–chattymin#456; 17 upstream commits). After merging, the fork is 0 commits behind upstream.Upstream highlights: alternate forms for Gen 1–5 species (chattymin#376), incremental Claude session-log parsing instead of re-reading whole files (chattymin#338), Cursor usage and limits sharing refreshed credentials (chattymin#455), no empty Settings windows on launch/reopen (chattymin#448), sprite animations recovering after failed downloads (chattymin#447), Pokédex Back returning to the viewed page and catch-log row (chattymin#435), collapsed backup history (chattymin#446), a labeled recap control (chattymin#432), repeated Rare Candy grants from volatile reset timestamps (chattymin#375), and a corrected Sonnet 5.5 cache-read price.
Conflict resolutions (7 files) and adaptations to fork-only code
ISO8601ParserModelPricingandISO8601ParserinPokeTokenBarShared(the iPhone ledger uses them), so upstream's changes are ported there. The Mac keeps its typealiases. The iPhone's own cost estimates get the price fix too._EmptyScene(). With noSettingsscene there's no system ⌘, item for the fork to retarget, soSettingsMenuItem.installnow adds the fork's own app-menu ⌘, item (or retargets one if the system made it). ⌘, still opens Settings inside the popover. TheSettingsSceneBridgefallback is unreachable without the scene and is removed. New tests cover insert, no-duplicate retarget, and no app menu.invalidate()deleted the only refresh token. Ported onto the fork'sAntigravityRefreshOutcomemodel: the credential is cached before the grant, and an expired credential with a.transientoutcome throwsAntigravityTokenRefreshError.transient(shown as the generic refresh message). Upstream's tests depend onMockOAuthURLProtocol/urlSession:, which the fork doesn't have, so they were rewritten onto the injectedtokenRefresher. The fork folds timeout/429/5xx into.transient, so one recovery test covers all three.UnownFormAPI. The phone payload stays Unown-only for now and is mapped from the newPokemonFormAPI; a new test ensures other species' forms (e.g. Sky Shaymin) aren't sent as Unown letters. Showing all forms on the iPhone is a follow-up.README.md,SettingsViewstate,defect-log.mdType of change
UI changes
The visible changes all come from upstream PRs, which were reviewed there with these images. The fork's merge resolution doesn't change their layout. Images are reused from the upstream PRs and labeled with their source.
More upstream images: catch-log row restore and the German/English cost rows in #435 and #432, expanded backup history in #446.
Fork-specific: ⌘, behaves as before (opens Settings in the popover), now through the fork's own app-menu item. Nothing about it looks different, so there's no image. The iPhone app's UI is unchanged in this PR.
Validation
swift buildpasses; the iOS app (PokeTokenBariOSscheme, simulator) builds../scripts/test-gate.sh: 1,780 tests, 19 skipped, 1 failure:UsageStoreTests.testKeychainDisabledRecordsNoHistory, a known local-only failure (a saved session key on this machine leaks in; it passes in CI). The full run skippedKeychainAutoPathTestsandIncrementalStoreScanTests, which stall locally on Keychain prompts; CI runs them.gitleaks detectoverorigin/main..HEAD: no leaks.Checklist
swift buildandswift testpass locally (build passes; one known local-only failure, see Validation)🤖 Generated with Claude Code